package com.duowan.cms.action;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.duowan.cms.common.domain.Page;
import com.duowan.cms.common.dto.UrlInfo;
import com.duowan.cms.common.exception.BaseCheckedException;
import com.duowan.cms.common.util.DateUtil;
import com.duowan.cms.common.util.PathUtil;
import com.duowan.cms.common.util.StringUtil;
import com.duowan.cms.dto.article.ArticleInfo;
import com.duowan.cms.dto.channel.ChannelInfo;
import com.duowan.cms.dto.channel.ChannelSearchCriteria;
import com.duowan.cms.dto.template.TemplateInfo;
import com.duowan.cms.dto.user.UserInfo;
import com.duowan.cms.dto.user.UserPowerInfo;
import com.duowan.cms.parser.rmi.client.template.TemplateBatchParserRemoteService;
import com.duowan.cms.service.article.ArticleService;
import com.duowan.cms.service.cdn.CdnService;
import com.duowan.cms.service.channel.ChannelService;
import com.duowan.cms.service.template.TemplateService;
import com.duowan.cms.service.user.UserService;
import com.duowan.cms.service.worklog.WorkLogService;

@Controller
public class ChannelController {

    @Autowired
    private TemplateBatchParserRemoteService templateBatchParserRemoteService;
    @Autowired
    private ArticleService articleService;
    @Autowired
    private ChannelService channelService;
    @Autowired
    private TemplateService templateService;
    @Autowired
    private CdnService cdnService;
    @Autowired
    private UserService userService;

    @Autowired
    private WorkLogService workLogService;

    private static Logger logger = Logger.getLogger(ChannelController.class);

    /**
     * 导航到频道主界面 
     */
    @RequestMapping(value = "/channel/toChannelMainPage", method = RequestMethod.GET)
    public String toRight(HttpServletRequest request, HttpServletResponse response) throws IOException {
        UserInfo userInfo = (UserInfo) request.getSession().getAttribute("userInfo");
        ChannelInfo channelInfo = (ChannelInfo) request.getSession().getAttribute("channelInfo");
        int workCount = workLogService.getMyWorkLog(channelInfo.getId(), userInfo.getUserId());
        request.setAttribute("workCount", workCount);// 登录者每天发了多少篇文章
        return "/channel/channel_main";
    }

    @RequestMapping(value = "/channel/quickEdit", method = RequestMethod.POST)
    public void quickEdit(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String url = request.getParameter("url");

        ChannelInfo channelInfo = (ChannelInfo) request.getSession().getAttribute("channelInfo");
        UrlInfo urlInfo = PathUtil.parser(url);
        if (urlInfo == null) {
            logger.info("快速编辑出错[URL不能被识别]:" + url);
            response.getWriter().write("fail:快速编辑出错[URL不能被识别]:" + url);
        } else if (UrlInfo.TYPE_ARTICLE == urlInfo.getType()) {
            ArticleInfo articleInfo = articleService.getByChannelIdAndArticleId(channelInfo.getId(), urlInfo.getId());
            if (articleInfo == null) {
                response.getWriter().write("fail:频道[" + channelInfo.getName() + "]找不到[id=" + urlInfo.getId() + "]的文章");
            } else {
                // 普通文章
                response.getWriter().write("success:/article/toEditArticlePage.do?articleId=" + urlInfo.getId() + "&channelId=" + channelInfo.getId());
            }
        } else if (UrlInfo.TYPE_TEMPLATE == urlInfo.getType()) {
            TemplateInfo templateInfo = templateService.getByChannelIdAndTemplateId(channelInfo.getId(), urlInfo.getId());
            if (templateInfo == null) {
                response.getWriter().write("fail:频道[" + channelInfo.getName() + "]找不到[id=" + urlInfo.getId() + "]的模板");
            } else {
                // 模板
                response.getWriter().write("success:/template/toEditTemplatePage.do?templateId=" + urlInfo.getId() + "&channelId=" + channelInfo.getId());
            }
        } else {
            logger.info("快速编辑出错[非法URL]:" + url);
            response.getWriter().write("fail:快速编辑出错[URL不能被识别]:" + url);
        }
    }

    /**
     * 手动同步文件
     */
    @RequestMapping(value = "/channel/sync_file", method = RequestMethod.GET)
    public String toSyncFilePage(HttpServletRequest request, HttpServletResponse response) throws IOException {
        return "/channel/sync_file";
    }

    /**
     * 刷新页面
     */
    @RequestMapping(value = "/channel/flushAll", method = RequestMethod.GET)
    public String toFlushAllPage(HttpServletRequest request, HttpServletResponse response) throws IOException {
        return "/channel/flush_all";
    }

    /**
     * 刷新本频道所有文章静态页
     */
    @RequestMapping(value = "/channel/flushCdnByUrl", method = RequestMethod.GET)
    public void flushCdnByUrl(HttpServletRequest request, HttpServletResponse response) throws IOException, BaseCheckedException {
    	String flushUrl = request.getParameter("flushUrl");
    	boolean result = cdnService.flushCdn(flushUrl);
    	if (result) {
    		logger.info("URL【"+flushUrl+"】刷新CDN成功");
			response.getWriter().write("刷新成功,最长五分钟内完成更新");
		}else{
			logger.info("URL【"+flushUrl+"】刷新CDN失败");
			response.getWriter().write("刷新失败");
		}
    }
    
    /**
     * 刷新本频道所有文章静态页
     */
    @RequestMapping(value = "/channel/flushCdnByDir", method = RequestMethod.GET)
    public void flushCdnByDir(HttpServletRequest request, HttpServletResponse response) throws IOException, BaseCheckedException {
    	String flushDir = request.getParameter("flushDir");
    	boolean result = cdnService.flushCdnDir(flushDir);
    	if (result) {
    		logger.info("目录【"+flushDir+"】刷新CDN成功");
			response.getWriter().write("刷新成功,最长五分钟内完成更新");
		}else{
			logger.info("目录【"+flushDir+"】刷新CDN失败");
			response.getWriter().write("刷新失败");
		}
    }
    
    
    
    
    /**
     * 刷新本频道所有文章静态页
     */
    @RequestMapping(value = "/channel/flushAllArticleInChannelId", method = RequestMethod.GET)
    public void flushAllArticleInChannelId(HttpServletRequest request, HttpServletResponse response) throws IOException {
        ChannelInfo channelInfo = (ChannelInfo) request.getSession().getAttribute("channelInfo");
        templateBatchParserRemoteService.flushAllArticleInChannelId(channelInfo.getId());
    }

    /**
     * 刷新本频道所有tag:
     */
    @RequestMapping(value = "/channel/flushAllTagInChannel", method = RequestMethod.GET)
    public void flushAllTagInChannel(HttpServletRequest request, HttpServletResponse response) throws IOException {
        ChannelInfo channelInfo = (ChannelInfo) request.getSession().getAttribute("channelInfo");
        templateBatchParserRemoteService.flushAllTagInChannel(channelInfo.getId());
    }

    /**
     * 刷新本频道所有模板:
     */
    @RequestMapping(value = "/channel/flushAllTemplateInChannnel", method = RequestMethod.GET)
    public void flushAllTemplateInChannnel(HttpServletRequest request, HttpServletResponse response) throws IOException {
        ChannelInfo channelInfo = (ChannelInfo) request.getSession().getAttribute("channelInfo");
        templateBatchParserRemoteService.flushAllTemplateInChannnel(channelInfo.getId());
    }
    /**
     * 刷新本频道指定时间后的文章静态页
     */
    @RequestMapping(value = "/channel/flushArticleAfterDateInChannelId", method = RequestMethod.GET)
    public void flushArticleAfterDateInChannelId(HttpServletRequest request, HttpServletResponse response) throws IOException {
        
        ChannelInfo channelInfo = (ChannelInfo) request.getSession().getAttribute("channelInfo");
        
        String dateStr = request.getParameter("dateStr");
        try {
            Date date = DateUtil.convertStr2Date(dateStr);
            templateBatchParserRemoteService.flushArticleAfterDateInChannelId(channelInfo.getId(), date);
        } catch (Exception e) {
            logger.warn("刷新频道["+channelInfo.getId()+"]指定时间["+dateStr+"]后的文章静态页异常", e);
        }
    }
    
    /**
     * 刷新本频道使用指定最终页模板的所有文章静态页
     */
    @RequestMapping(value = "/channel/flushByArticleTemplateId", method = RequestMethod.GET)
    public void flushByArticleTemplateId(HttpServletRequest request, HttpServletResponse response) throws Exception {
        ChannelInfo channelInfo = (ChannelInfo) request.getSession().getAttribute("channelInfo");
        String articleTemplateId = request.getParameter("articleTemplateId");
        if(StringUtil.isNumber(articleTemplateId)){
            try {
                templateBatchParserRemoteService.flushByArticleTemplateId(channelInfo.getId(), articleTemplateId);
            } catch (Exception e) {
                logger.warn("刷新频道["+channelInfo.getId()+"]使用指定最终页模板["+articleTemplateId+"]的所有文章静态页", e);
            }
        }
    }

    @RequestMapping(value = "/channel/channelManage", method = RequestMethod.GET)
    public String channelManage(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // ChannelInfo channelInfo =
        // (ChannelInfo)request.getSession().getAttribute("channelInfo");
        // templateFlushService.flushAllTemplateInChannnel(channelInfo.getId());
        request.getSession().removeAttribute("channelInfo");
        request.setAttribute("categoryList", ChannelInfo.CATEGORY_LIST);
        return "/channel/channelManage";
    }

    @RequestMapping(value = "/channel/allChannelInfo", method = RequestMethod.GET)
    public String channelInfo(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // ChannelInfo channelInfo =
        // (ChannelInfo)request.getSession().getAttribute("channelInfo");
        // templateFlushService.flushAllTemplateInChannnel(channelInfo.getId());
        request.getSession().removeAttribute("channelInfo");

        UserInfo userInfo = (UserInfo) request.getSession().getAttribute("userInfo");
        if (!userInfo.isAdmin()) {// 非管理员无法进入
            return "redirect:/toErrorPage.do?errorMessage=" + URLEncoder.encode("你没有[系统管理员]权限", "UTF-8");
        }
        configChannelInfoList(request);
        return "/channel/allChannelInfo";
    }
    
    @RequestMapping(value = "/channel/updateChannelInfo", method = RequestMethod.POST)
    public void updateChannelInfo(HttpServletRequest request, HttpServletResponse response, @ModelAttribute("channelInfo") ChannelInfo newChannelInfo) throws Exception {
        UserInfo userInfo = (UserInfo) request.getSession().getAttribute("userInfo");
        if (!userInfo.isAdmin()) {// 非管理员无法进入
            response.getWriter().write("fail:not admin!");
            return ;
        }
        String _channelId = request.getParameter("_channelId");
        String _category = request.getParameter("_category");
        try{
            ChannelInfo channelInfo = channelService.getById(_channelId);
            if(null != channelInfo){
                channelInfo.setCategory(_category);
                channelService.updateChannelInfo(channelInfo);
                response.getWriter().write("success");
            }
        }catch(Exception e){
            response.getWriter().write("fail:未知异常!");
            logger.warn("修改频道信息出错", e);
        }
        
    }
    

    private void configChannelInfoList(HttpServletRequest request) {
        String type = request.getParameter("type");
        String searchkey = request.getParameter("searchkey");
        String pageNo = request.getParameter("pageNo");
        String category = request.getParameter("category");
        // 将searchkey中的特殊字符替换，防止存在跨站脚本攻击安全漏洞
        searchkey = StringUtil.clearHTML(searchkey);

        // 设置列表信息
        ChannelSearchCriteria searchCriteria = new ChannelSearchCriteria();
        searchCriteria.setPageSize(20);
        if(!StringUtil.isEmpty(category)){
            searchCriteria.setCategory(category);
        }
        if("byId".equals(type)){
            if (!StringUtil.isEmpty(searchkey))
                searchCriteria.setId(searchkey);
        }else if("byName".equals(type)){
            if (!StringUtil.isEmpty(searchkey))
                searchCriteria.setName(searchkey);
        }
        if (!StringUtil.isEmpty(pageNo)) {
            searchCriteria.setPageNo(Integer.parseInt(pageNo));
        }
        Page<ChannelInfo> channelInfoPage = channelService.pageSearch(searchCriteria);
        request.setAttribute("channelInfoPage", channelInfoPage);

        // 设置"上一个请求的查询条件"到页面
        request.setAttribute("searchkey", "null".equals(searchkey) ? "" : searchkey);
        request.setAttribute("type", StringUtil.isEmpty(type) ? "byName" : type);
        request.setAttribute("queryStr", "&searchkey=" + searchkey + "&type=" + type + "&category=" + category);
        //设置分类信息
        request.setAttribute("categoryList", ChannelInfo.CATEGORY_LIST);
    }

    @RequestMapping(value = "/channel/checkNewChannelId", method = RequestMethod.GET)
    public void checkNewChannelId(HttpServletRequest request, HttpServletResponse response) throws IOException {

        String id = request.getParameter("newChannelId");

        if (StringUtil.isEmpty(id) || null != channelService.getById(id.trim())) {
            response.getWriter().write("fail");
        } else {
            response.getWriter().write("success");
        }
    }

    @RequestMapping(value = "/channel/checkNewChannelName", method = RequestMethod.GET)
    public void checkNewChannelName(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String name = request.getParameter("newChannelName");

        if (StringUtil.isEmpty(name) || null != channelService.getByName(name.trim())) {
            response.getWriter().write("fail");
        } else {
            response.getWriter().write("success");
        }
    }

    @RequestMapping(value = "/channel/openNewChannel", method = RequestMethod.POST)
    public void openNewChannel(HttpServletRequest request, HttpServletResponse response, @ModelAttribute("channelInfo") ChannelInfo newChannelInfo) throws Exception {

        UserInfo userInfo = (UserInfo) request.getSession().getAttribute("userInfo");
        String editorStr = request.getParameter("mainEditor");
        try {
            if (!userInfo.isAdmin())
                throw new Exception(userInfo.getUserId() + "无权限开通新专区");
            if(null !=channelService.getById(newChannelInfo.getId())){
                response.getWriter().write("专区["+newChannelInfo.getId()+"]已经存在");
                return;
            }
            // 新开专区
            @SuppressWarnings("deprecation")
            String logoPath = request.getRealPath("/favicon.ico");
            channelService.openNewChannel(newChannelInfo, logoPath);
            //为userInfo添加权限信息
            List<UserPowerInfo> userPowerInfoList = userService.getAllPowerByUyserId(userInfo.getUserId());
            userInfo.setAllChannelPowerInfo(userPowerInfoList);
            String failName = addMainEditorToNewChannel(editorStr, newChannelInfo, userInfo.getUserId());
            if (StringUtil.isEmpty(failName)) {
                response.getWriter().write("success");
            } else {
                response.getWriter().write(failName);
            }
        } catch (BaseCheckedException bce) {
            response.getWriter().write("加入主编时出错，请在专区中加入主编");
            logger.error("开专区加入主编出现问题：", bce);
        } catch (Exception e) {
            response.getWriter().write("fail");
            logger.error("开专区失败！原因：", e);
        }

    }

    private String addMainEditorToNewChannel(String editorStr, ChannelInfo newChannelInfo, String admin) throws BaseCheckedException {

        StringBuffer sb = new StringBuffer();

        if (!StringUtil.isEmpty(editorStr)) {
            String[] mainEditors = editorStr.split("，|、");
            List<UserInfo> list = new ArrayList<UserInfo>();
            for (String userId : mainEditors) {
                UserInfo userInfo = userService.getById(userId);
                if (null != userInfo && !userInfo.isAdmin()) {
                    list.add(userInfo);
                } else {
                    sb.append(userId).append(",");
                }
            }
            channelService.addMainEditorToNewChannel(list, newChannelInfo, admin);
        }

        return sb.toString();
    }

    @RequestMapping(value = "/channel/uplineChannel", method = RequestMethod.POST)
    public void uplineChannel(HttpServletRequest request, HttpServletResponse response) throws Exception {

        try {
            String channelId = request.getParameter("channelId");

            ChannelInfo channelInfo = channelService.getById(channelId);

            if (null != channelInfo && !channelInfo.isUpline()) {
                channelService.upline(channelInfo);
                response.getWriter().write("success");
            } else {
                response.getWriter().write("该专区已经上线");
            }
        } catch (Exception e) {
            logger.error("专区上线失败！原因：", e);
            response.getWriter().write("fail");
        }
    }

    @RequestMapping(value = "/channel/downlineChannel", method = RequestMethod.POST)
    public void downlineChannel(HttpServletRequest request, HttpServletResponse response) throws Exception {

        try {
            String channelId = request.getParameter("channelId");

            ChannelInfo channelInfo = channelService.getById(channelId);

            if (null != channelInfo && channelInfo.isUpline()) {
                channelService.downline(channelInfo);
                response.getWriter().write("success");
            } else {
                response.getWriter().write("该专区已经下线");
            }
        } catch (Exception e) {
            logger.error("专区下线失败！原因：", e);
            response.getWriter().write("fail");
        }
    }

    @RequestMapping(value = "/channel/important", method = RequestMethod.GET)
    public String important(HttpServletRequest request, HttpServletResponse response) throws Exception {

        String channelId = request.getParameter("channelId");
        channelService.important(channelId);
        return "redirect:/channel/allChannelInfo.do";
    }
    
    @RequestMapping(value = "/channel/unimportant", method = RequestMethod.GET)
    public String unimportant(HttpServletRequest request, HttpServletResponse response) throws Exception {

        String channelId = request.getParameter("channelId");
        channelService.unimportant(channelId);
        return "redirect:/channel/allChannelInfo.do";
    }
    
    @RequestMapping(value = "/channel/resource", method = RequestMethod.GET)
    public void getResource(HttpServletRequest request, HttpServletResponse response) throws Exception {

        String channelId = request.getParameter("channelId");
        String src = request.getParameter("src");
        if(StringUtil.isEmpty(src)){
            return ;
        }
        if(src.endsWith(".pdf")){
            response.setContentType("application/pdf");
        }
        try{
            String path = null;
            if(!StringUtil.isEmpty(channelId)){
                path = "/WEB-INF/resource/" + channelId + "/" + src;
            }else{
                path = "/WEB-INF/resource/" + src;
            }
            
            InputStream in = request.getSession().getServletContext().getResourceAsStream(path);
            
            if(null == in){
                logger.info("请求资源:[" + src + "]不存在");
                return;
            }
            
            OutputStream out = response.getOutputStream();
            
            byte[] buffer = new byte[1024];
            int length = -1;
            while((length = in.read(buffer)) != -1){
                out.write(buffer, 0, length);
            }
            in.close();
            out.close();
            
        }catch(Exception e){
            logger.warn("请求资源有误!", e);
        }
    }

}
